package com.xu.tools.util;

import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author xuguan
 * @date 2022/11/22
 * @desc HttpConnectionUrl工具类
 */
public class HttpConnectionUrlUtil {

    private static final int CONNECT_TIMEOUT = 10 * 1000;
    private static final int READ_TIMEOUT = 10 * 1000;
    private static final boolean DO_INPUT = true;
    private static final boolean DO_OUTPUT = true;
    private static final Map<String, String> defaultRequestPropertyMap = new LinkedHashMap<>(8);

    static {
        defaultRequestPropertyMap.put("Accept", "*/*");
        defaultRequestPropertyMap.put("Content-Type", "application/json;charset=utf-8");
    }

    public static HttpURLConnection defaultGetHttpUrlConnection(String url) {
        return defaultGetHttpUrlConnection(url, null);
    }

    public static HttpURLConnection defaultGetHttpUrlConnection(String url, String authorization) {
        if (StringUtils.hasText(authorization)) {
            defaultRequestPropertyMap.put("Authorization", authorization);
        }
        return createHttpUrlConnection(url, "GET", defaultRequestPropertyMap);
    }

    public static HttpURLConnection defaultPostHttpUrlConnection(String url) {
        return defaultPostHttpUrlConnection(url, null);
    }

    public static HttpURLConnection defaultPostHttpUrlConnection(String url, String authorization) {
        if (StringUtils.hasText(authorization)) {
            defaultRequestPropertyMap.put("Authorization", authorization);
        }
        return createHttpUrlConnection(url, "POST", defaultRequestPropertyMap);
    }

    public static HttpURLConnection defaultPostFormHttpUrlConnection(String url) {
        return defaultPostFormHttpUrlConnection(url, null);
    }

    public static HttpURLConnection defaultPostFormHttpUrlConnection(String url, String authorization) {
        defaultRequestPropertyMap.put("Content-Type", "application/x-www-form-urlencoded");
        if (StringUtils.hasText(authorization)) {
            defaultRequestPropertyMap.put("Authorization", authorization);
        }
        return createHttpUrlConnection(url, "POST", defaultRequestPropertyMap);
    }

    public static HttpURLConnection createHttpUrlConnection(String url, String method, Map<String, String> requestPropertyMap) {
        HttpURLConnection connection = null;
        try {
            connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setConnectTimeout(CONNECT_TIMEOUT);
            connection.setReadTimeout(READ_TIMEOUT);
            // 支持输入输出
            connection.setDoInput(DO_INPUT);
            connection.setDoOutput(DO_OUTPUT);

            // 设置请求方法
            connection.setRequestMethod(method);

            // 设置请求头
            for (Map.Entry<String, String> entry : requestPropertyMap.entrySet()) {
                connection.setRequestProperty(entry.getKey(), entry.getValue());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        assert connection != null;
        return connection;
    }

    public static String sendGet(String url, Map<String, String> params) {
        return sendGet(defaultGetHttpUrlConnection(buildQueryUrl(url, params)));
    }

    public static String sendGet(HttpURLConnection connection) {
        try {
            // 开始连接
            connection.connect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return inputStreamToStr(connection);
    }

    public static String sendPostForm(String url, String requestContent) {
        return sendPost(defaultPostFormHttpUrlConnection(url), requestContent);
    }

    public static String sendPostForm(String url, Map<String, String> params) {
        String requestContent = null;
        if (!CollectionUtils.isEmpty(params)) {
            StringBuffer sb = new StringBuffer();
            int i = 0;
            for (Map.Entry<String, String> entry : params.entrySet()) {
                sb.append(entry.getKey()).append("=").append(entry.getValue());
                if (i < params.size() - 1) {
                    sb.append("&");
                    i++;
                }
            }
            requestContent = sb.toString();
        }
        return sendPost(defaultPostFormHttpUrlConnection(url), requestContent);
    }

    public static String sendPost(String url, String requestContent) {
        return sendPost(defaultPostHttpUrlConnection(url), requestContent);
    }

    public static String sendPost(HttpURLConnection connection, String requestContent) {
        try {
            // 开始连接
            connection.connect();
            if (StringUtils.hasText(requestContent)) {
                try (OutputStream os = connection.getOutputStream()) {
                    os.write(requestContent.getBytes(StandardCharsets.UTF_8));
                    os.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return inputStreamToStr(connection);
    }

    private static String inputStreamToStr(HttpURLConnection connection) {
        StringBuilder response = new StringBuilder();
        try (
                InputStream is = connection.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))
        ) {
            String tmp = "";
            while ((tmp = br.readLine()) != null) {
                response.append(tmp);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            connection.disconnect();
        }
        return response.toString();
    }

    public static String buildQueryUrl(String baseUrl, Map<String, String> params) {
        if (CollectionUtils.isEmpty(params)) {
            return baseUrl;
        }
        UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUrl);
        for (String key : params.keySet()) {
            String value = params.get(key);
            try {
                key = URLEncoder.encode(key, "UTF-8");
                value = URLEncoder.encode(value, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            uriComponentsBuilder.queryParam(key, value);
        }
        return uriComponentsBuilder.build().toUriString();
    }
}
